/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include "引擎枚举数据.h"
#include "引擎数据类型.h"
#include <三角形.h>

typedef void(*fn_空间划分_数据添加删除)(void* data);

EngineAPI_EXPORT S_点距八叉树* f_空间划分_create球形八叉树(float32 空间大小);
EngineAPI_EXPORT void	f_空间划分_destroy球形八叉树(S_点距八叉树* t);



EngineAPI_EXPORT void	f_空间划分_add子集(S_点距八叉树* t, const vec3& pos, const float32 半径, void* data);
EngineAPI_EXPORT S_八叉树子空间*	f_空间划分_add子集(S_点距八叉树* t, const vec3& pos, const float32 半径);
EngineAPI_EXPORT void	f_空间划分_从包围盒构建子集(S_点距八叉树* t, const std::vector<S_Sphere>& 包围盒);
EngineAPI_EXPORT void	f_空间划分_remove子集(S_点距八叉树* t, const vec3& pos);
EngineAPI_EXPORT void	f_空间划分_remove所有子集(S_点距八叉树* t);


EngineAPI_EXPORT void	f_空间划分_get位置子集数据(S_点距八叉树* t, const vec3& pos, std::vector<void*>& data);
EngineAPI_EXPORT void	f_空间划分_get射线子集数据(S_点距八叉树* t, const vec3& 开始, const vec3& 结束, std::vector<S_八叉树子空间*>& data);
EngineAPI_EXPORT void	f_空间划分_线段查子空间(const S_点距八叉树* t, const S_线段& line, std::vector<S_八叉树子空间*>& data);

EngineAPI_EXPORT void	f_空间划分_get范围子集数据(const S_点距八叉树* t, const S_Sphere& 范围, std::vector<S_八叉树子空间*>& data, bool 是否包含数据 = false);
EngineAPI_EXPORT void	f_空间划分_set叉树空间大小(S_点距八叉树* t, float32 空间大小, vec3 offset);
EngineAPI_EXPORT void	f_空间划分_从坐标索引(S_点距八叉树* t, const std::vector<S_Sphere>& 包围盒);




EngineAPI_EXPORT void	f_空间划分_解析为坐标(const S_点距八叉树* t, std::vector<vec4>& pos, bool 是否包含数据 = false);
EngineAPI_EXPORT void	f_空间划分_单元解析为坐标(const S_点距八叉树* t, std::vector<vec4>& pos);
EngineAPI_EXPORT void	f_空间划分_射线拾取结果解析为域坐标(S_点距八叉树* t, vec3 开始, const vec3& 结束, std::vector<vec4>& data);
EngineAPI_EXPORT void	f_空间划分_范围拾取解析为域坐标(S_点距八叉树* t, const S_Sphere& 范围, std::vector<vec4>& data);



template<typename T>
struct S_球形四叉树 {
	S_球形四叉树*	m_子节点[4];
	vec2				m_坐标;
	float32				m_半径;
	std::set<T>			m_数据;

	S_球形四叉树(vec2 原点 = {}, float32 半径 = 1.0) {
		for (uint32 i = 0; i < 4; ++i) {
			m_子节点[i] = nullptr;
		}
		m_坐标 = 原点;
		m_半径 = 半径;

	}
	~S_球形四叉树() {
		for (uint32 i = 0; i < 4; ++i) {
			if(m_子节点[i]) delete m_子节点[i];
		}
	}
};


template<typename T>
void f_shapeTree_添加数据(S_球形四叉树<T>& tree, T data, vec2 坐标, float32 数据半径) {
	
	if (数据半径 < tree.m_半径) {
		uint8 index = 0;

		float32 h = tree.m_半径 * 0.5;
		vec2 p = 坐标 - tree.m_坐标;

		vec2 lv;

		if (p.y >= 0) {
			index = 2;
			lv.y = tree.m_坐标.y + h;
		}
		else {
			index = 0;
			lv.y = tree.m_坐标.y - h;
		}

		if (p.x >= 0) {
			index += 1;
			lv.x = tree.m_坐标.x + h;
		}
		else {
			lv.x = tree.m_坐标.x - h;
		}

		S_球形四叉树<T>* st = tree.m_子节点[index];
		if (tree.m_子节点[index]) {
			
		}
		else {
			st = new S_球形四叉树<T>(lv, h);
			tree.m_子节点[index] = st;
		}

		f_shapeTree_添加数据(*st, data, 坐标, 数据半径);
	}
	else {
		tree.m_数据.insert(data);
	}

}

template<typename T>
void f_shapeTree_查找数据(S_球形四叉树<T>& tree, vec2 坐标, float32 数据半径, std::vector<std::set<T>*>& 返回数据) {

	for (uint32 i = 0; i < 4; ++i) {
		if (!tree.m_子节点[i]) continue;

		auto& st = *tree.m_子节点[i];
		//const auto* st = tree.m_子节点[i];
		float32 r = st.m_半径;
		vec2 p = abs(坐标 - (st.m_坐标)) - 数据半径 - 1e-7;


		if (p.x <= r && p.y <= r) {
			返回数据.push_back(&st.m_数据);

			f_shapeTree_查找数据(st, 坐标, 数据半径, 返回数据);
		}
	}
}






struct S_2D扫描线段 {
	//uvec2	索引;
	//vec2	端点;
	vec2 起点;
	vec2 方向;

	float32 梯度;
	float32 终点;
	
	uint32	边ID;
	uint32	边;
};

struct S_2D扫描交点 {
	vec2	交点;
	uint32	边ID;
	uint32	边;
};

class C_线扫描包围体 {
	std::vector<std::vector<S_2D扫描线段>> m_线段;
	float32 m_分割层厚度;
	float32 m_高度;
	float32 m_底边;
public:
	C_线扫描包围体 (float32 厚度);
	~C_线扫描包围体 ();

	uint32 f_构建包围层(const S_2D线段路径& edgeIndices);

	std::vector<S_2D扫描交点> f_扫描(float32 步进, float32 采样厚度);

private:
	
};








//template<typename T>
//void f_shapeTree_删除数据(S_球形四叉树<T>& tree, vec2 坐标, float32 数据半径, const T& 数据) {
//	
//	for (uint32 i = 0; i < 4; ++i) {
//		if (!tree.m_子节点[i]) continue;
//
//		auto& st = *tree.m_子节点[i];
//		//const auto* st = tree.m_子节点[i];
//		float32 r = st.m_半径;
//		vec2 p = abs(坐标 - (st.m_坐标)) - 数据半径 - 1e-7;
//
//
//		if (p.x <= r && p.y <= r) {
//			st.m_数据.erase(数据);
//
//			f_shapeTree_查找数据(st, 坐标, 数据半径, 数据);
//		}
//	}
//}

//template<typename T>
//void f_shapeTree_查找数据2(const S_球形四叉树<T>& tree, vec2 坐标, float32 数据半径, std::vector<T&>& 返回数据) {
//
//	for (uint32 i = 0; i < 4; ++i) {
//		if (!tree.m_子节点[i]) continue;
//
//		auto& st = *tree.m_子节点[i];
//		//const auto* st = tree.m_子节点[i];
//		float32 r = st.m_半径;
//		vec2 p = abs(坐标 - (st.m_坐标)) - 数据半径 - 1e-7;
//
//
//		if (p.x <= r && p.y <= r) {
//			返回数据.insert(返回数据.end(), st.m_数据);
//
//			f_shapeTree_查找数据(st, 坐标, 数据半径, 返回数据);
//		}
//	}
//}

